﻿#include "../src/QueueStack.hpp"

#define CATCH_CONFIG_MAIN
#include <catch2/catch_all.hpp>
#include <catch2/catch_test_macros.hpp>
#include <mutex>
#include <thread>

// NOLINTBEGIN
TEST_CASE("SPSCRingBuffer基本功能测试", "[spsc][basic]") {
  WinstJackonw::SPSCRingBuffer<int, 8> buffer;  // 容量为7

  SECTION("初始状态为空") {
    REQUIRE(buffer.IsEmpty() == true);
    REQUIRE(buffer.IsFull() == false);
    REQUIRE(buffer.capacity() == 7);
  }

  SECTION("单元素Push/Pop操作") {
    REQUIRE(buffer.Push(42) == true);
    REQUIRE(buffer.IsEmpty() == false);

    auto result = buffer.Pop();
    REQUIRE(result.has_value() == true);
    REQUIRE(result.value() == 42);
    REQUIRE(buffer.IsEmpty() == true);
  }

  SECTION("多元素顺序测试") {
    for (int i = 1; i <= 5; i++) {
      REQUIRE(buffer.Push(i) == true);
    }

    for (int i = 1; i <= 5; i++) {
      auto result = buffer.Pop();
      REQUIRE(result.has_value() == true);
      REQUIRE(result.value() == i);
    }
    REQUIRE(buffer.IsEmpty() == true);
  }
}

TEST_CASE("SPSCRingBuffer边界条件测试", "[spsc][boundary]") {
  WinstJackonw::SPSCRingBuffer<int, 8> buffer;  // 实际容量7

  SECTION("填满缓冲区") {
    for (int i = 0; i < buffer.capacity(); i++) {
      REQUIRE(buffer.Push(i) == true);
    }
    REQUIRE(buffer.IsFull() == true);

    SECTION("满时Push失败") { REQUIRE(buffer.Push(999) == false); }

    SECTION("清空缓冲区") {
      for (int i = 0; i < buffer.capacity(); i++) {
        auto result = buffer.Pop();
        REQUIRE(result.has_value() == true);
      }
      REQUIRE(buffer.IsEmpty() == true);

      SECTION("空时Pop返回nullopt") {
        auto result = buffer.Pop();
        REQUIRE(result.has_value() == false);
      }
    }
  }
}

TEST_CASE("SPSCRingBuffer数据类型测试", "[spsc][types]") {
  SECTION("内置数据类型测试") {
    WinstJackonw::SPSCRingBuffer<double, 4> doubleBuffer;
    REQUIRE(doubleBuffer.Push(3.14) == true);
    auto result = doubleBuffer.Pop();
    REQUIRE(result.value() == Catch::Approx(3.14));
  }

  SECTION("自定义结构体测试") {
    struct Point {
      int x, y;
      bool operator==(const Point& other) const {
        return x == other.x && y == other.y;
      }
    };

    WinstJackonw::SPSCRingBuffer<Point, 4> pointBuffer;
    REQUIRE(pointBuffer.Push(Point{1, 2}) == true);
    auto result = pointBuffer.Pop();
    REQUIRE(result.value() == Point{1, 2});
  }
}

TEST_CASE("SPSCRingBuffer容量验证", "[spsc][capacity]") {
  SECTION("不同容量测试") {
    WinstJackonw::SPSCRingBuffer<int, 16> buffer16;  // 2的幂次
    REQUIRE(buffer16.capacity() == 15);

    WinstJackonw::SPSCRingBuffer<int, 32> buffer32;
    REQUIRE(buffer32.capacity() == 31);
  }
}

// 并发测试（基础版本）
TEST_CASE("SPSCRingBuffer并发安全测试", "[spsc][concurrent]") {
  WinstJackonw::SPSCRingBuffer<int, 1024> buffer;

  SECTION("单生产者单消费者模式") {
    const int test_count = 1000;

    // 生产者线程（这里用循环模拟）
    for (int i = 0; i < test_count; i++) {
      buffer.Push(i);
    }

    // 消费者线程（这里用循环模拟）
    for (int i = 0; i < test_count; i++) {
      auto result = buffer.Pop();
      REQUIRE(result.has_value() == true);
      // 注意：由于是并发环境，顺序可能不保证，这里只检查是否成功
    }
  }
}

// 参数化测试 - 使用Catch2的GENERATE
TEST_CASE("参数化Push/Pop测试", "[spsc][generators]") {
  auto [input, expected] =
      GENERATE(std::make_tuple(1, 1), std::make_tuple(-1, -1),
               std::make_tuple(0, 0), std::make_tuple(1000, 1000));

  WinstJackonw::SPSCRingBuffer<int, 4> buffer;
  CAPTURE(input);  // 测试失败时显示输入值

  REQUIRE(buffer.Push(input) == true);
  auto result = buffer.Pop();
  REQUIRE(result.value() == expected);
}

// 使用BDD风格编写测试
SCENARIO("SPSCRingBuffer完整工作流程", "[spsc][bdd]") {
  GIVEN("一个空的SPSCRingBuffer") {
    WinstJackonw::SPSCRingBuffer<int, 8> buffer;

    WHEN("向缓冲区添加多个元素") {
      REQUIRE(buffer.Push(10) == true);
      REQUIRE(buffer.Push(20) == true);
      REQUIRE(buffer.Push(30) == true);

      THEN("可以按顺序取出元素") {
        REQUIRE(buffer.Pop().value() == 10);
        REQUIRE(buffer.Pop().value() == 20);
        REQUIRE(buffer.Pop().value() == 30);
      }

      AND_WHEN("填满缓冲区后再清空") {
        for (int i = 0; i < buffer.capacity(); i++) {
          buffer.Push(i);
        }

        THEN("缓冲区已满") { REQUIRE(buffer.IsFull() == true); }

        THEN("可以完全清空缓冲区") {
          for (int i = 0; i < buffer.capacity(); i++) {
            REQUIRE(buffer.Pop().has_value() == true);
          }
          REQUIRE(buffer.IsEmpty() == true);
        }
      }
    }
  }
}
TEST_CASE("SPSCRingBuffer多线程安全测试", "[concurrency][thread-safe]") {
  constexpr size_t Capacity = 1024;
  constexpr int TotalElements = 10000;
  WinstJackonw::SPSCRingBuffer<int, Capacity> buffer;
  std::atomic<bool> producerFinished{false};
  std::atomic<int> consumedCount{0};
  std::vector<int> consumedValues;
  std::mutex consumedMutex;

  SECTION("单生产者单消费者基础测试") {
    auto producer = [&]() {
      for (int i = 0; i < TotalElements; ++i) {
        while (!buffer.Push(i)) {
          std::this_thread::yield();  // 队列满时等待
        }
      }
      producerFinished = true;
    };

    auto consumer = [&]() {
      while (!producerFinished || !buffer.IsEmpty()) {
        auto value = buffer.Pop();
        if (value.has_value()) {
          std::lock_guard<std::mutex> lock(consumedMutex);
          consumedValues.push_back(value.value());
          consumedCount++;
        } else {
          std::this_thread::yield();
        }
      }
    };

    std::thread producerThread(producer);
    std::thread consumerThread(consumer);

    producerThread.join();
    consumerThread.join();

    REQUIRE(consumedValues.size() == TotalElements);

    // 验证顺序一致性（SPSC应该保持顺序）
    for (size_t i = 0; i < consumedValues.size(); ++i) {
      REQUIRE(consumedValues[i] == static_cast<int>(i));
    }
  }

  SECTION("高负载并发测试") {
    constexpr int HighLoadElements = 100000;
    std::atomic<int> producedCount{0};

    auto highLoadProducer = [&]() {
      for (int i = 0; i < HighLoadElements; ++i) {
        while (!buffer.Push(i)) {
          std::this_thread::yield();
        }
        producedCount++;
      }
      producerFinished = true;
    };

    auto highLoadConsumer = [&]() {
      int lastValue = -1;
      while (!producerFinished || !buffer.IsEmpty()) {
        auto value = buffer.Pop();
        if (value.has_value()) {
          // 验证值单调递增（SPSC特性）
          REQUIRE(value.value() > lastValue);
          lastValue = value.value();
          consumedCount++;
        }
      }
    };

    std::thread producerThread(highLoadProducer);
    std::thread consumerThread(highLoadConsumer);

    producerThread.join();
    consumerThread.join();

    REQUIRE(consumedCount == HighLoadElements);
  }
}
// NOLINTEND
